package com.qf.service.impl;

import com.qf.constant.CacheConstants;
import com.qf.constant.StrategyConstants;
import com.qf.dfa.SensitiveWordFilter;
import com.qf.feign.CacheService;
import com.qf.model.StandardSubmit;
import com.qf.service.StrategyService;
import com.qf.util.PushMsgUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;

import java.io.IOException;
import java.io.StringReader;
import java.util.HashSet;
import java.util.Set;

/**
 * 敏感词策略
 * @author lenovo
 * @version V1.0
 * @Date 2021/11/22 21:37
 */
@Component(value = "dirtyWords")
@Slf4j
public class DirtyWordsFilterServiceImpl implements StrategyService {

    @Autowired
    private PushMsgUtil pushMsgUtil;

    @Autowired
    private CacheService cacheService;

    @Override
    public Boolean execute(StandardSubmit standardSubmit) {
        log.info("【策略模块 - 敏感词策略】开始执行，短信对象内容 standardSubmit={}", standardSubmit);

        //使用ik分词器
        //1.获取用户输入的短信内容
        String messageContent = standardSubmit.getMessageContent();

        //2.对短信内容使用ik分词器分词
        StringReader stringReader = new StringReader(messageContent);
        IKSegmenter ik = new IKSegmenter(stringReader, true);

        //3.遍历分词器分出来的全部词汇，去redis中依次匹配
        Lexeme lexeme = null;
        while (true){
            try {
                if ((lexeme = ik.next()) == null){
                    //ik分词器已经遍历完
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            //4.获取分词器分出来的词,作为key去redis中的脏词库匹配
            String word = lexeme.getLexemeText();
            String value = cacheService.get(CacheConstants.CACHE_PREFIX_DIRTY_WORDS + word);

            if (!StringUtils.isEmpty(value)){
                //如果不为空，则说明分出来的词包含脏词
                log.info("【策略模块 - 敏感词策略】短信发送失败，短信内容有敏感词!!! 短信对象standardSubmit={}，敏感词word={}",standardSubmit,word);
                pushMsgUtil.pushReport(standardSubmit, StrategyConstants.STRATEGY_ERROR_DIRTY_WORDS);
                pushMsgUtil.sendLog(standardSubmit,StrategyConstants.STRATEGY_ERROR_DIRTY_WORDS);
                return false;
            }
        }

        //5.如果循环结束，没有匹配到脏词，说明，校验通过
        log.info("【策略模块 - 敏感词策略】执行成功，短信对象内容 standardSubmit={}",standardSubmit);
        return true;
    }

    /**
     * 使用工具类，dfa算法
     * @param standardSubmit
     * @return
     */
    public Boolean daf(StandardSubmit standardSubmit){
        //1.获取敏感词的过滤器对象
        SensitiveWordFilter filter = SensitiveWordFilter.getInstance();

        //2.查看敏感词信息
        int num = filter.checkSensitiveWord(standardSubmit.getMessageContent(), 0, SensitiveWordFilter.minMatchType);

        //3.判断敏感词数量
        if (num == 0){
            //没有敏感词
            log.info("【策略模块 - 敏感词策略】执行成功，短信对象内容 standardSubmit={}",standardSubmit);
            return true;

        }else {
            //有敏感词，不允许短信发送
            log.info("【策略模块 - 敏感词策略】短信发送失败，短信内容有敏感词!!! 短信对象standardSubmit={}",standardSubmit);
            pushMsgUtil.pushReport(standardSubmit, StrategyConstants.STRATEGY_ERROR_DIRTY_WORDS);
            pushMsgUtil.sendLog(standardSubmit,StrategyConstants.STRATEGY_ERROR_DIRTY_WORDS);
            return false;
        }
    }

    /**
     * 使用set集合的方式
     * @param standardSubmit
     * @return
     */
    public Boolean excute2(StandardSubmit standardSubmit){

        String messageContent = standardSubmit.getMessageContent();
        StringReader reader = new StringReader(messageContent);
        IKSegmenter ik = new IKSegmenter(reader, true);

        HashSet<String> ikWrods = new HashSet<>();
        Lexeme lexeme = null;
        while (true){
            try {
                if ((lexeme = ik.next()) == null){
                    break;
                }
                ikWrods.add(lexeme.getLexemeText());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //判断分完词的短信内容和redis脏词库的脏词有没有交集
        Set<String> res = cacheService.interSet(ikWrods);

        if (res.size() > 0){
            //如果不为空，则说明分出来的词包含脏词
            log.info("【策略模块 - 敏感词策略】短信发送失败，短信内容有敏感词!!! 短信对象standardSubmit={}",standardSubmit);
            pushMsgUtil.pushReport(standardSubmit, StrategyConstants.STRATEGY_ERROR_DIRTY_WORDS);
            pushMsgUtil.sendLog(standardSubmit,StrategyConstants.STRATEGY_ERROR_DIRTY_WORDS);
            return false;
        }

        //5.如果循环结束，没有匹配到脏词，说明，校验通过
        log.info("【策略模块 - 敏感词策略】执行成功，短信对象内容 standardSubmit={}",standardSubmit);
        return true;
    }
}
